﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

namespace Lab01Server
{
    class Program
    {
        protected int _server_port;
        protected Dictionary<int, int[]> _requests;
        protected Dictionary<int, int[]> _response;
        public Program(int port)
        {
            _server_port = port;
            _requests = new Dictionary<int, int[]>();
            _response = new Dictionary<int, int[]>();
        }

        public void Start()
        {
            try
            {
                IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _server_port);
                Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                server.Bind(ipep);
                server.Listen(20);
                Console.WriteLine("Server started on port:{0}", _server_port);
                while (true)
                {
                    Socket socket = server.Accept();
                    Console.WriteLine("Client connected:{0}", ((IPEndPoint)socket.RemoteEndPoint).Address);
                    BinaryFormatter bf = new BinaryFormatter();
                    NetworkStream ns = new NetworkStream(socket);
                    Int32 id=(Int32)bf.Deserialize(ns);

                    switch (id)
                    {
                        case 1: AddArray(socket,ns); break;
                        case 2: ShowServerArray(socket,ns); break;
                        case 3: Process(socket,ns); break;
                        case 4: ShowResult(socket,ns); break;
                    }
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Disconnect(false);
                    Console.WriteLine("Disconnectd");
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void AddArray(Socket socket, NetworkStream ns)
        {
            Console.WriteLine("AddArray");
            BinaryFormatter bf = new BinaryFormatter();
            int[] array = (int[])bf.Deserialize(ns);
            Int32 index = _requests.Count;
            _requests.Add(index, array);
            Int32 error_code = 0;
            bf.Serialize(ns, error_code);
            bf.Serialize(ns, index);
        }

        public void ShowServerArray(Socket socket,NetworkStream ns)
        {
            Console.WriteLine("ShowServerArray");
            BinaryFormatter bf = new BinaryFormatter();
            Int32 index = (Int32)bf.Deserialize(ns);
            Int32 error_code = 0;
            if (_requests.ContainsKey(index))
            {
                bf.Serialize(ns, error_code);
                int[] array = _requests[index];
                bf.Serialize(ns, array);
            } else
            {
                Console.WriteLine("Sending error");
                error_code = 1;
                bf.Serialize(ns, error_code);
            }
        }

        public void Process(Socket socket, NetworkStream ns)
        {
            Console.WriteLine("Process");
            BinaryFormatter bf = new BinaryFormatter();
            Int32 index = (Int32)bf.Deserialize(ns);
            Int32 error_code = 0;
            if (_requests.ContainsKey(index))
            {
                bf.Serialize(ns, error_code);
                int[] array = _requests[index];
                int[] result = new int[array.Length];
                for (int i = 0; i < array.Length; i++) result[i] = array[i] * 2;
                _response.Add(index, result);
            }
            else
            {
                Console.WriteLine("Sending error");
                error_code = 1;
                bf.Serialize(ns, error_code);
            }
            return;
        }

        public void ShowResult(Socket socket, NetworkStream ns)
        {
            Console.WriteLine("ShowResult");
            BinaryFormatter bf = new BinaryFormatter();
            Int32 index = (Int32)bf.Deserialize(ns);
            Int32 error_code = 0;
            if (_requests.ContainsKey(index))
            {
                bf.Serialize(ns, error_code);
                int[] array = _response[index];
                bf.Serialize(ns, array);
            } else
            {
                Console.WriteLine("Sending error");
                error_code = 1;
                bf.Serialize(ns, error_code);
            }
        }


        static void Main(string[] args)
        {
            new Program(1930).Start();
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }
}
